package com.mianyang.zhangsan.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.mianyang.zhangsan.common.util.CommonUtils;
import com.mianyang.zhangsan.common.util.StringUtils;
import com.mianyang.zhangsan.model.dto.SecAccountRole;
import com.mianyang.zhangsan.model.dto.SecRoleDto;
import com.mianyang.zhangsan.model.entity.SecAuthority;
import com.mianyang.zhangsan.model.entity.SecRole;
import com.mianyang.zhangsan.mapper.SecRoleMapper;
import com.mianyang.zhangsan.model.entity.SecRoleAuthority;
import com.mianyang.zhangsan.service.ISecAuthorityService;
import com.mianyang.zhangsan.service.ISecRoleService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.mianyang.zhangsan.service.ISecUserRoleService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author jiangjr
 * @since 2022-10-23
 */
@Service
public class SecRoleServiceImpl extends ServiceImpl<SecRoleMapper, SecRole> implements ISecRoleService {
    @Autowired
    private ISecUserRoleService userRoleService;
    @Autowired
    private ISecAuthorityService authorityService;

    @Override
    public List<SecRole> selectRolesByUserId(Long userId) {
        List<Long> roles = userRoleService.selectRoles(userId);
        return listByIds(roles);
    }

    @Override
    public List<SecAuthority> selectRoleAndAuth(Long roleId) {
        return authorityService.selectAuthByRoleId(roleId);
    }

    @Override
    public List<SecAuthority> selectAuthority(Long accountId) {
        // 根据用户与角色关系查询用户角色
        List<Long> roleIds = userRoleService.selectRoles(accountId);

        return selectAuthorityByRoles(roleIds);
    }

    @Override
    public List<SecAuthority> selectAuthorityByRoles(List<Long> roleIds) {
        // 根据角色与权限关系查询用户权限
        if (CommonUtils.isNotEmpty(roleIds)) {
            List<SecRole> accountRoles = listByIds(roleIds);
            // 查询所有角色
            List<SecRole> allRoles = list();
            // 找到角色之间的继承关系，继承父级角色的权限
            accountRoles.forEach(item -> {
                List<SecRole> parentRoles = findParent(allRoles, item.getParentId());
                List<Long> parentIds = parentRoles.stream().map(SecRole::getRoleId).collect(Collectors.toList());
                roleIds.addAll(parentIds);
            });

            return authorityService.selectAuthorities(roleIds);
        }
        return null;
    }

    @Override
    public Page<SecRole> selectRoles(String roleName, int current, int pageSize) {
        QueryWrapper<SecRole> wrapper = new QueryWrapper<>();
        if (StringUtils.isNotEmpty(roleName)) {
            wrapper.like("role_name", roleName);
        }
        return page(new Page<>(current, pageSize), wrapper);
    }

    private List<SecRole> findParent(List<SecRole> roles, Long parentId) {
        List<SecRole> parentRoles = new ArrayList<>();
        for (SecRole role : roles) {
            if(role.getRoleId().equals(parentId)) {
                parentRoles.add(role);
                if (role.getParentId().equals(0L)) {
                    return parentRoles;
                }
                List<SecRole> parentRoleIds = findParent(roles, role.getParentId());
                parentRoles.addAll(parentRoleIds);
            }
        }
        return parentRoles;
    }

    @Override
    public void saveRoleAndAuthority(SecRoleDto role) {
        SecRole saveRole = role.getRole();
        save(saveRole);
        updateRoleAndAuthRelation(role, saveRole);
    }

    @Override
    public SecAccountRole selectAccountRoles(Long accountId) {
        List<Long> roleIds = userRoleService.selectRoles(accountId);
        List<SecRole> currentRoles = new ArrayList<>();
        List<SecRole> roles = listByIds(roleIds);
        List<SecRole> allRoles = list();
        roles.forEach(role -> {
            List<SecRole> parentRoles = findParent(allRoles, role.getParentId());
            currentRoles.addAll(parentRoles);
        });
        currentRoles.addAll(roles);
        SecAccountRole accountRole = new SecAccountRole();
        accountRole.setAllRoles(allRoles);
        accountRole.setCurrentRoles(currentRoles);
        return accountRole;
    }

    @Override
    public void updateRoleAndAuthority(SecRoleDto role) {
        SecRole updateRole = role.getRole();
        updateById(updateRole);

        updateRoleAndAuthRelation(role, updateRole);
    }

    private void updateRoleAndAuthRelation(SecRoleDto role, SecRole updateRole) {
        List<Long> authorities = role.getAuthorities();
        if(CommonUtils.isNotEmpty(authorities)) {
            List<SecRoleAuthority> roleAuthorities = authorities.stream().map(auth -> {
                return SecRoleAuthority.builder()
                        .authorityId(auth)
                        .roleId(updateRole.getRoleId())
                        .build();
            }).collect(Collectors.toList());
            authorityService.updateRoleAndAuthRelation(updateRole.getRoleId(), roleAuthorities);
        }
    }
}
